﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;
using eTerm.NetSocket.PlugIn;
namespace eTerm.NetSocket
{
    #region 客户端模型
    public class eTerm363Session : TSessionBase
    {
        #region 变量定义
        private long? m_SessionTimeout = null;
        private long m_DatagramSequence = 0;
        #endregion

        #region 属性定义
        /// <summary>
        /// Gets or sets the name of the group.
        /// </summary>
        /// <value>The name of the group.</value>
        public long GroupCode { set; get; }

        /// <summary>
        /// 是否结口用户
        /// </summary>
        public bool IsApiSession { set; get; }

        /// <summary>
        /// 帐户到期日期
        /// </summary>
        public DateTime? ExpireDate { get; set; }


        /// <summary>
        /// Gets or sets the RID.
        /// </summary>
        /// <value>The RID.</value>
        public byte RID { get; set; }

        /// <summary>
        /// Gets or sets the SID.
        /// </summary>
        /// <value>The SID.</value>
        public byte SID { get; set; }

        /// <summary>
        /// Gets or sets the e term session.
        /// </summary>
        /// <value>The e term session.</value>
        public BaseTermSocket eTermSession { get; set; }

        /// <summary>
        /// 禁用指令.
        /// </summary>
        /// <value>The forbidden command.</value>
        public List<string> ForbiddenCommand { get; set; }

        /// <summary>
        /// 特殊指令时限列表(格式为：AV|20).
        /// </summary>
        /// <value>The special command.</value>
        public Dictionary<string,int> SpecialCommand { get; set; }

        /// <summary>
        /// Gets or sets the validate T session.
        /// </summary>
        /// <value>The validate T session.</value>
        public TSessionValidateCallBack ValidateTSession { get; set; }

        /// <summary>
        /// 联系电话
        /// </summary>
        public string Mobile { get; set; }

        /// <summary>
        /// Email地址
        /// </summary>
        public string Email { get; set; }

        /// <summary>
        /// 剩余指令数
        /// </summary>
        public long Surplus { get; set; }

        /// <summary>
        /// 联系人
        /// </summary>
        public string DisplayName { get; set; }

        public bool AllowDuplicate { get; set; }
        #endregion

        #region 构造函数
        /// <summary>
        /// Initializes a new instance of the <see cref="eTerm363Session"/> class.
        /// </summary>
        public eTerm363Session() {
            RID = 0x27; //(byte)new Random().Next(0x20,0x50);
            SID = 0x51;
            ForbiddenCommand = new List<string>();
            SpecialCommand = new Dictionary<string, int>();
            m_DatagramSequence = 0;
        }

        /// <summary>
        /// Fires the on timeout.
        /// </summary>
        //private void FireOnTimeout() {
        //    lock (this)
        //    {
        //        if (OnTSessionTimeout != null)
        //            OnTSessionTimeout(this, new TSessionEventArgs(this));
        //        if (eTermSession == null) return;
        //        eTermSession.TSession.SendDatagram(__eTermPakcet.BuildSessionPacket(RID, SID, @"注意,配置已释放."));
        //        eTermSession.TSession = null;
        //        if(eTermSession!=null)
        //            eTermSession.SendStream(@"IG");
        //        eTermSession = null;
        //    }
        //}
        #endregion

        #region 重写
        /// <summary>
        /// 重写错误处理方法, 返回消息给客户端
        /// </summary>
        protected override void OnDatagramDelimiterError()
        {
            base.OnDatagramDelimiterError();

            base.SendDatagram("datagram delimiter error");
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        protected override void Dispose()
        {
            base.Dispose();
            //if (m_ResetEvent != null)
            //{
            //    m_ResetEvent.Dispose();
            //    m_ResetEvent = null;
            //}
        }

        /// <summary>
        /// 重写错误处理方法, 返回消息给客户端
        /// </summary>
        protected override void OnDatagramOversizeError()
        {
            base.OnDatagramOversizeError();

            base.SendDatagram("datagram over size");
        }


        /// <summary>
        /// 提取包时与包规则紧密相关，根据实际规则重定义
        /// </summary>
        /// <param name="readBytesLength"></param>
        protected override void ResolveSessionBuffer(int readBytesLength)
        {
            this.GetDatagramFromBuffer(0, readBytesLength);
        }
        #endregion

        #region 用户认证
        public delegate bool TSessionValidateCallBack(eTerm363Session TSession, byte[] datagramBytes);

        /// <summary>
        /// 解包用户登录信息(校验用户信息).
        /// </summary>
        /// <param name="Pakcet">The pakcet.</param>
        private void UnpakcetSession(byte[] buffer)
        {
            byte[] userBytes = new byte[16];
            byte[] passBytes = new byte[16];
            Buffer.BlockCopy(buffer, 2, userBytes, 0, 16);
            Buffer.BlockCopy(buffer, 18, passBytes, 0, 16);
            m_name = Encoding.Default.GetString(userBytes).Replace("\0", "");
        }
        #endregion


        /// <summary>
        /// 重写 AnalyzeDatagram 方法, 调用数据存储方法
        /// </summary>
        protected override void AnalyzeDatagram(byte[] datagramBytes)
        {
            Interlocked.Increment(ref m_DatagramSequence);
            #region 指令数判断
            if (!string.IsNullOrEmpty(Name)&& --Surplus <= 0) {
                m_state = TSessionState.Shutdown;
                OnSessionReceiveException(new NotSupportedException(string.Format( @"终端 {0} 指令超限强制退出",Name)));
                Close();
                return;
            }
            #endregion
            
            if (m_DatagramSequence==1)
            {                 //握手包
                //if (datagramBytes[1] == 0xA2) 
                {             //登录包 
                    if (ValidateTSession!=null&&ValidateTSession(this, datagramBytes))
                    {
                        base.SendDatagram(new byte[] { 
                            0x00,0x14,0x01,0x00,0x03,0x00,0x00,0x00,RID,SID,0x0C,0x00,0x00,0x8C,0x8C,0x29,
                            0x00,0x00,0xA9,0xA9 
                            });
                    }
                    else {
                        base.SendDatagram(new byte[] { 
                             0x00,0x37,0x00,0x31,0x30,0x30,0x30,0x31,0x3A,0x20,0xB5,0xC7,0xC2,0xBC,0xCA,0xA7
                            ,0xB0,0xDC,0xA3,0xBA,0xC7,0xEB,0xBC,0xEC,0xB2,0xE9,0xD3,0xC3,0xBB,0xA7,0xC3,0xFB 
                            ,0xBA,0xCD,0xBF,0xDA,0xC1,0xEE,0xA3,0xAC,0xBB,0xF2,0xD5,0xDF,0xC8,0xCF,0xD6,0xA4 
                            ,0xC0,0xE0,0xD0,0xCD,0xA3,0xA1,0x00 
                            });
                        Close();
                        return;
                    }

                       // }), this, 1000,System.Threading.Timeout.Infinite);                            
                }
                //else if (datagramBytes[1] == 0xFE)
                //{
                //    base.SendDatagram(new byte[] { 
                //                0x01,0xFD,0x00,0x06,0x00,0x00,0x01,0xFD,0x00,0x06,0x00,0x0C,0x01,0xFD,0x00,0x06,0x00,0x29 });
                //}
            }
            else if (m_DatagramSequence==2)
            {                                       //欢迎包
                //base.SendDatagram(__eTermPakcet.WELCOME_LOGIN);
                base.SendDatagram(new byte[] { 
                                0x01,0xFD,0x00,0x06,0x00,0x00
                            });
                Thread.Sleep(500);
                base.SendDatagram(new byte[] { 
                                0x01,0xFD,0x00,0x06,0x00,0x0C
                            });
                Thread.Sleep(500);
                base.SendDatagram(new byte[] { 
                                0x01,0xFD,0x00,0x06,0x00,0x29 
                            });
                if (!IsApiSession) {
                    Thread.Sleep(500);
                    //new System.Threading.Timer(new TimerCallback(delegate(object tSession)
                    //{
                    this.SendDatagram(__eTermPakcet.BuidAlertMessage(string.Format(@"系统信息：
        帐号：{0}
        有效期：{1}
        通用时限：{2}(秒)
        指令余量:{3}(条)", Name, (ExpireDate ?? DateTime.Now).ToLongDateString(), Timeout, Surplus)));
                }

            }
//            else if (m_DatagramSequence == 3) {
//                //base.SendDatagram(__eTermPakcet.WELCOME_LOGIN);
//                base.SendDatagram(__eTermPakcet.BuildSessionPacket(RID,SID, string.Format(@"欢迎使用PID共享服务器企业版
//帐户到期日期:{0}
//剩余指令数  :{1}", (ExpireDate??DateTime.Now).ToString(@"yyyy-MM-dd"),Surplus)));
//            }
            else if (datagramBytes[1] == 0x00) {
                base.OnDatagramAccepted();          //数据包
                bool isNew = false;
                List<string> CmdAry = new List<string>();
                string Cmd = string.Empty;
                #region 指令分析
                if (datagramBytes[8] == RID && datagramBytes[9] == SID) {
                    try {
                        Cmd = Encoding.GetEncoding("gb2312").GetString(UnpackPakcet(datagramBytes));
                        CmdAry.AddRange(Cmd.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
                    }
                    catch { }
                }
                #endregion

                #region 指令插件拦截处理
                if (CmdAry.Count > 0) {
                    IPlugIn plugIn = eTermThreadPool.Instance.GetPlugIn(CmdAry);
                    if (plugIn != null) {
                        try {
                            plugIn.Execute(eTermSession, this, Cmd);
                        }
                        catch { }
                        return;
                    }
                }
                #endregion

                #region 数据转发
                if (eTermSession == null || (eTermSession != null && !eTermSession.IsValidated))
                {
                    eTermSession = eTermThreadPool.Instance.Dequeue(this, out isNew);
                }
                else {
                    eTermSession = (SessionTimeInterval >= Timeout) ? eTermThreadPool.Instance.Dequeue(this, out isNew) : eTermSession;
                }

                if (eTermSession == null) {
                    base.SendDatagram(__eTermPakcet.BuildSessionPacket(RID, SID, @"无可用配置,请稍候!"));
                    return;
                }
                eTermSession.TSession = this;

                #region 特殊指令时限处理
                try {
                    if (!string.IsNullOrEmpty(Cmd) && SpecialCommand.Count(t => Regex.IsMatch(Cmd, @"^" + t.Key.Replace(@"\", @"\\"), RegexOptions.IgnoreCase | RegexOptions.Multiline)) > 0) {
                        m_SessionTimeout = Timeout;
                        Timeout = SpecialCommand.FirstOrDefault(t => !string.IsNullOrEmpty(Cmd) && Regex.IsMatch(Cmd, t.Key, RegexOptions.IgnoreCase | RegexOptions.Multiline)).Value;
                    }
                    else {
                        Timeout = m_SessionTimeout ?? Timeout;
                    }
                }
                catch { }
                #endregion

                #region 指令拦截处理
                try {
                    if (CmdAry.Count(c => (ForbiddenCommand.Count(t => Regex.IsMatch(c, @"^" + t.Replace(@"\", @"\\"), RegexOptions.IgnoreCase | RegexOptions.Multiline)) > 0)) > 0) {
                        string lst = string.Join(",", CmdAry.Where(c => (ForbiddenCommand.Count(t => Regex.IsMatch(c.Trim(), @"^" + t.Replace(@"\", @"\\"), RegexOptions.IgnoreCase | RegexOptions.Multiline)) > 0)).ToArray());
                        base.SendDatagram(__eTermPakcet.BuildSessionPacket(RID, SID, string.Format(@"指令 {0} 未授权", lst)));
                        return;
                    }
                }
                catch { }
                #endregion

                if (datagramBytes[8] == RID && datagramBytes[9] == SID) {
                    datagramBytes[8] = eTermSession.RID;
                    datagramBytes[9] = eTermSession.SID;
                }
                eTermSession.SendStream(datagramBytes);
                #endregion

                #region 后续插件处理
                //if (CmdAry.Count > 0)
                //{
                //}
                #endregion
            }
        }


        /// <summary>
        /// 自定义的数据存储方法
        /// </summary>
        private void Store(BaseTermSocket eTermSession,eTerm363Session TSession, byte[] datagramBytes)
        {
        }


        #region 解码逻辑
        /// <summary>
        /// 数据解码(适用不同类型客户端).
        /// </summary>
        /// <returns></returns>
        public byte[] UnpackPakcet(byte[] OriginalBytes)
        {
            return Unpacket(OriginalBytes);
        }


        /// <summary>
        /// Unpackets the specified LPS buf.
        /// </summary>
        /// <param name="lpsBuf">The LPS buf.</param>
        /// <returns></returns>
        private byte[] Unpacket(byte[] lpsBuf)
        {
            List<byte> UnPacketResult = new List<byte>();
            ushort nIndex = 18;
            ushort maxLength = BitConverter.ToUInt16(new byte[] { lpsBuf[3], lpsBuf[2] }, 0);
            while (nIndex++ < maxLength)
            {
                if (nIndex >= lpsBuf.Length) break;
                switch (lpsBuf[nIndex])
                {
                    case 0x1C:                          //红色标记
                    case 0x1D:
                        UnPacketResult.Add(0x20);
                        break;
                    case 0x62:
                    case 0x03:
                    case 0x1E:
                    case 0x1B:
                    case 0x00:
                        break;
                    case 0x0E:
                        while (true)
                        {
                            byte[] ch = new byte[] { lpsBuf[++nIndex], lpsBuf[++nIndex] };
                            if ((ch[0] == 0x1B) && (ch[1] == 0x0F))
                            {
                                break;
                            }
                            UsasToGb(ref ch[0], ref ch[1]);
                            UnPacketResult.AddRange(new byte[] { ch[0], ch[1] });
                        }
                        break;
                    default:
                        UnPacketResult.Add(lpsBuf[nIndex]);
                        break;
                }
            }
            return UnPacketResult.ToArray();
        }

        /// <summary>
        /// Usases to gb.
        /// </summary>
        /// <param name="c1">The c1.</param>
        /// <param name="c2">The c2.</param>
        private void UsasToGb(ref byte c1, ref byte c2)
        {
            if ((c1 > 0x24) && (c1 < 0x29))
            {
                byte tmp = c1;
                c1 = c2;
                c2 = (byte)(tmp + 10);
            }
            if (c1 > 0x24)
            {
                c1 = (byte)(c1 + 0x80);
            }
            else
            {
                c1 = (byte)(c1 + 0x8e);
            }
            c2 = (byte)(c2 + 0x80);
        }
        #endregion

    }
    #endregion

    #region 数据库操作模型
    public sealed class eTermDatabase : TSqlServerBase { 
        
    }
    #endregion

}
